package cn.xiangxu.demo.sell_demo.service.impl;


import cn.xiangxu.demo.sell_demo.dao.OrderDetailDao;
import cn.xiangxu.demo.sell_demo.dao.OrderMasterDao;
import cn.xiangxu.demo.sell_demo.dao.ProductInfoDao;
import cn.xiangxu.demo.sell_demo.entity.entityDTO.CarDTO;
import cn.xiangxu.demo.sell_demo.entity.entityDTO.OrderDTO;
import cn.xiangxu.demo.sell_demo.entity.entityPO.OrderDetailPO;
import cn.xiangxu.demo.sell_demo.entity.entityPO.OrderMasterPO;
import cn.xiangxu.demo.sell_demo.entity.entityPO.ProductInfoPO;
import cn.xiangxu.demo.sell_demo.enums.OrderStatusEnum;
import cn.xiangxu.demo.sell_demo.enums.PayStatusEnum;
import cn.xiangxu.demo.sell_demo.enums.ResultEnum;
import cn.xiangxu.demo.sell_demo.exceptions.SellException;
import cn.xiangxu.demo.sell_demo.service.OrderService;
import cn.xiangxu.demo.sell_demo.service.ProductInfoService;
import cn.xiangxu.demo.sell_demo.service.SellerInfoService;
import cn.xiangxu.demo.sell_demo.util.KeyUtil;
import cn.xiangxu.demo.sell_demo.util.converter.OrderMasterPO2OrderDTOConverter;
import com.fasterxml.jackson.databind.util.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.smartcardio.Card;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static cn.xiangxu.demo.sell_demo.enums.ResultEnum.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 王杨帅
 * @since 2018-04-21
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    private final String className = getClass().getName();

    @Autowired
    private ProductInfoDao productInfoDao;

    @Autowired
    private OrderDetailDao orderDetailDao;

    @Autowired
    private OrderMasterDao orderMasterDao;

    @Autowired
    private ProductInfoService productInfoService;

    @Override
    @Transactional
    public OrderDTO create(OrderDTO orderDTO) {

        /** 订单总价 */
        BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO);

        /** 生产订单Id */
        String orderId = KeyUtil.genUniqueKey();

        // 01 商品信息判断
        for (OrderDetailPO orderDetailPO : orderDTO.getOrderDetailPOList()) {
            // 0101 根据商品ID查询啥品信息
            Optional<ProductInfoPO> productInfoPOOptional = productInfoDao.findById(orderDetailPO.getProductId());

            // 0102 如果查到的商品商品信息为空就抛出异常：商品信息不存在
            if (!productInfoPOOptional.isPresent()) {
                throw new SellException(ResultEnum.PRODUCT_INFO_NOT_EXIST);
            }
            ProductInfoPO productInfoPO = productInfoPOOptional.get();

            // 0103 如果查询到商品信息，就封装订单详情信息并进行订单详情入库
            // 010301 计算订单总价
            orderAmount = productInfoPO.getProductPrice()
                            .multiply(new BigDecimal(orderDetailPO.getProductQuantity()))
                            .add(orderAmount);
            // 010302 订单详情封装
            BeanUtils.copyProperties(productInfoPO, orderDetailPO);
            orderDetailPO.setDetailId(KeyUtil.genUniqueKey());
            orderDetailPO.setOrderId(orderId);
            // 010303 订单详情入库
            orderDetailDao.save(orderDetailPO);

        }

        // 02 订单入库
        // 0201 订单信息封装
        OrderMasterPO orderMasterPO = new OrderMasterPO();
        orderDTO.setOrderId(orderId);
        BeanUtils.copyProperties(orderDTO, orderMasterPO);
        orderMasterPO.setOrderAmount(orderAmount);
        orderMasterPO.setOrderStatus(OrderStatusEnum.NEW.getCode());
        orderMasterPO.setPayStatus(PayStatusEnum.WAIT.getCode());

        // 0202 点单信息入库
        orderMasterDao.save(orderMasterPO);

        // 03 扣库存
        // 0301 封装购物车列表
        List<CarDTO> carDTOList
                = orderDTO.getOrderDetailPOList()
                .stream()
                .map(e -> new CarDTO(e.getProductId(), e.getProductQuantity()))
                .collect(Collectors.toList());

        // 0302 调用商品服务层进行扣库存操作
        productInfoService.decreaseStock(carDTOList);

        return orderDTO;
    }

    @Override
    @Transactional
    public OrderDTO findByOrderId(String orderId) {
        // 01 根据订单ID到订单表中去查询订单基本信息
        Optional<OrderMasterPO> orderMasterPOOptional = orderMasterDao.findById(orderId);
        // 0101 如果查询到的数据为空，就抛出异常：订单基本信息为空
        if (!orderMasterPOOptional.isPresent()) {
            throw new SellException(ResultEnum.ORDER_INFO_IS_NULL);
        }
        // 0102 从查询结果中获取订单基本信息
        OrderMasterPO orderMasterPO = orderMasterPOOptional.get();

        // 02 根据订单ID到订单详情表中去查询订单基本信息
        List<OrderDetailPO> orderDetailPOList = orderDetailDao.findByOrOrderId(orderId);
        // 0201 如果查询到的数据为空，就抛出异常：订单详情信息为空
        if (orderDetailPOList.isEmpty()) {
            throw new SellException(ResultEnum.ORDER_DETAIL_INFO_IS_NULL);
        }

        // 03 将订单基本信息和订单详情信息进行整合
        OrderDTO orderDTO = new OrderDTO();
        // 0301 订单基本信息整合
        BeanUtils.copyProperties(orderMasterPO, orderDTO);
        // 0302 订单详情信息整合
        orderDTO.setOrderDetailPOList(orderDetailPOList);

        return orderDTO;
    }

    @Override
    @Transactional
    public Page<OrderDTO> findList(String buyerOpenid, Pageable pageable) {
        // 01 根据买家的微信ID以及分页对象查询订单信息
        Page<OrderMasterPO> orderMasterPOPage = orderMasterDao.findByBuyerOpenid(buyerOpenid, pageable);

        // 02 将查询到的 OrderMasterPO 转化成 OrderDTO
        List<OrderDTO> orderDTOList = OrderMasterPO2OrderDTOConverter.convert(orderMasterPOPage.getContent());

        // 03 数据封装
        Page<OrderDTO> result = new PageImpl<OrderDTO>(orderDTOList, pageable, orderMasterPOPage.getTotalElements());

        // 04 数据返回
        return result;
    }

    @Override
    public OrderDTO cancel(OrderDTO orderDTO) {
        // 01 判断订单状态，如果订单状态处于已完结状态就抛出异常：订单已经完结，不能取消
        if (!OrderStatusEnum.NEW.getCode().equals(orderDTO.getOrderStatus())) {
            log.error("===/" + className + "/cancel====【订单状态不正确】-orderId={},orderStatus={}", orderDTO.getOrderId(), orderDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }

        // 02 修改订单状态
        OrderMasterPO orderMasterPO = new OrderMasterPO();
        orderDTO.setOrderStatus(OrderStatusEnum.CANCEL.getCode());
        BeanUtils.copyProperties(orderDTO, orderMasterPO);
        OrderMasterPO updateResult = orderMasterDao.save(orderMasterPO);
        if (updateResult == null) {
            log.error("===/" + className + "/cancel===【更新订单状态失败】-orderMasterPO={}", orderMasterPO);
            throw new SellException(ResultEnum.ORDER_UPDATE_STATUS_ERROR);
        }

        // 03 修改库存
        // 0301 判断订单中是否有商品
        if (CollectionUtils.isEmpty(orderDTO.getOrderDetailPOList())) {
            log.error("===/" + className + "/cancel===【该订单无任何商品信息】- orderDTO={}", orderDTO);
            throw new SellException(ResultEnum.ORDER_PRODUCT_LIST_IS_NULL);
        }
        // 0301 加库存操作
        List<CarDTO> carDTOList =
                orderDTO.getOrderDetailPOList()
                .stream()
                .map(e -> new CarDTO(e.getProductId(), e.getProductQuantity()))
                .collect(Collectors.toList());
        productInfoService.increseStock(carDTOList);

        // 04 如果已经支付需要退款
        if (PayStatusEnum.SUCCESS.getCode().equals(orderDTO.getPayStatus())) {
            // TODO:
        }

        // 05 返回订单信息
        return orderDTO;
    }

    @Override
    public OrderDTO finish(OrderDTO orderDTO) {
        // 01 判断订单状态
        if (!OrderStatusEnum.NEW.getCode().equals(orderDTO.getOrderStatus())) {
            log.error("===/" + className + "/finish====【订单状态不正确】-orderId={},orderStatus={}", orderDTO.getOrderId(), orderDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);

        }

        // 02 修改订单状态
        OrderMasterPO orderMasterPO = new OrderMasterPO();
        orderDTO.setOrderStatus(OrderStatusEnum.FINISHED.getCode());
        BeanUtils.copyProperties(orderDTO, orderMasterPO);
        OrderMasterPO finishResult = orderMasterDao.save(orderMasterPO);
        if (finishResult == null) {
            log.error("===/" + className + "/finish===【更新订单状态失败】-orderMasterPO={}", orderMasterPO);
            throw new SellException(ResultEnum.ORDER_UPDATE_STATUS_ERROR);
        }

        // 03 返回订单信息
        return orderDTO;
    }

    @Override
    public OrderDTO paid(OrderDTO orderDTO) {
        // 01 判断订单状态
        if (!OrderStatusEnum.NEW.getCode().equals(orderDTO.getOrderStatus())) {
            log.error("===/" + className + "/paid====【订单状态不正确】-orderId={},orderStatus={}", orderDTO.getOrderId(), orderDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }

        // 02 判断订单支付状态
        if (!PayStatusEnum.WAIT.getCode().equals(orderDTO.getPayStatus())) {
            log.error("===/" + className + "/paid====【订单支付状态不正确】-orderId={},orderPayStatus={}", orderDTO.getOrderId(), orderDTO.getPayStatus());
            throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR);
        }

        // 03 修改订单支付状态
        OrderMasterPO orderMasterPO = new OrderMasterPO();
        orderDTO.setPayStatus(PayStatusEnum.SUCCESS.getCode());
        BeanUtils.copyProperties(orderDTO, orderMasterPO);
        OrderMasterPO payResult = orderMasterDao.save(orderMasterPO);
        if (payResult == null) {
            log.error("===/" + className + "/paid===【更新订单支付状态失败】-orderMasterPO={}", orderMasterPO);
            throw new SellException(ResultEnum.ORDER_UPDATE_PAY_SATTUS_ERROR);
        }

        // 04 返回订单信息
        return orderDTO;
    }
}
